#include <iostream>
#include <unistd.h>
#include <signal.h>

// block表和pending表的关系：
// block为1，pending为0：主动屏蔽了某个信号，block置1
// block为1，pending为1：主动屏蔽了某个信号，block置1，屏蔽之后再次接收到了该信号，pending置1
// block为0，pending为1，解除了block对某个信号的屏蔽，判断pending是否为1，为1则执行该信号，为0则不做操作
void Print(sigset_t &pending)
{
    for(int signo = 31; signo >= 1;signo--)
    {
        if(sigismember(&pending,signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << "\n\n";
}
void handler(int signo)
{
    std::cout << "catch a signo: " << signo << std::endl;
}

// int main()
// {
//     // 0. 对2号信号进行自定义捕捉
//     signal(2,handler);

//     // 1. 先对2号信号进行屏蔽
//     sigset_t bset,oset;
//     // 将内部清空
//     sigemptyset(&bset);
//     sigemptyset(&oset);
//     // 准备一份要屏蔽信号的位图
//     sigaddset(&bset,2);
//     // sigaddset(&bset,13);
//     // 1.2 调用系统调用，将准备好的位图设置进内核
//     // SIG_SETMASK：覆盖式的设置，同时将修改前的位图存入oset
//     sigprocmask(SIG_SETMASK,&bset,&oset);

//     // 2. 重复打印当前进程的pending和block
//     sigset_t pending;
//     int cnt = 0;
//     while(true)
//     {
//         // 2.1 获取进程pending
//         int n = sigpending(&pending);
//         if(n < 0)
//             continue;
        
//         // 2.2 打印
//         std::cout << "block: " << std::endl;
//         Print(bset);

//         std::cout << "pending: " << std::endl;
//         Print(pending);

//         sleep(1);
//         cnt++;

//         // 2.3 解除阻塞
//         if(cnt == 20)
//         {
//             std::cout << "unblock 2 signo" << std::endl;
//             // 还原信号集
//             sigprocmask(SIG_SETMASK,&oset,nullptr);
//         }
//     }

//     return 0;
// }

// 测试是否屏蔽了所有信号
// 9号信号和19号信号无法被屏蔽
int main()
{
    sigset_t bset,oset;
    sigemptyset(&bset);
    sigemptyset(&oset);
    for(int i = 1;i <= 31;i++)
    {
        sigaddset(&bset,i);
    }
    sigprocmask(SIG_SETMASK,&bset,&oset);

    sigset_t pending;
    while(true)
    {
        // 获取
        int n = sigpending(&pending);
        if(n < 0)
            continue;
        
        // 打印
        Print(pending);
        sleep(1);
    }

    return 0;
}